Micron Document
🎖️GitЯра🎖️


Displaying Raw • Download

androidApp/src/fdroid/kotlin/org/meshtastic/app/map/discovery/DiscoveryOsmMap.kt 2d20cd8a4708e2ef66e98d5259f3a97ec93f240a (2d20cd8a) Text, 6.80 KB

T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tf0883e@fileTb4b4b4:Te6edf3SuppressTb4b4b4(Ta5d6ff"Ta5d6ffMagicNumberTa5d6ff"Tb4b4b4)

Tff7b72package T7ee787org.meshtastic.app.map.discovery

Tff7b72import T7ee787android.graphics.Paint
Tff7b72import T7ee787androidx.compose.runtime.Composable
Tff7b72import T7ee787androidx.compose.runtime.LaunchedEffect
Tff7b72import T7ee787androidx.compose.runtime.getValue
Tff7b72import T7ee787androidx.compose.runtime.mutableStateOf
Tff7b72import T7ee787androidx.compose.runtime.remember
Tff7b72import T7ee787androidx.compose.runtime.setValue
Tff7b72import T7ee787androidx.compose.ui.Modifier
Tff7b72import T7ee787androidx.compose.ui.graphics.toArgb
Tff7b72import T7ee787androidx.compose.ui.platform.LocalContext
Tff7b72import T7ee787androidx.compose.ui.platform.LocalDensity
Tff7b72import T7ee787androidx.compose.ui.unit.dp
Tff7b72import T7ee787androidx.compose.ui.viewinterop.AndroidView
Tff7b72import T7ee787org.meshtastic.app.map.addCopyright
Tff7b72import T7ee787org.meshtastic.app.map.addScaleBarOverlay
Tff7b72import T7ee787org.meshtastic.app.map.model.CustomTileSource
Tff7b72import T7ee787org.meshtastic.app.map.rememberMapViewWithLifecycle
Tff7b72import T7ee787org.meshtastic.app.map.zoomIn
Tff7b72import T7ee787org.meshtastic.core.common.util.MetricFormatter
Tff7b72import T7ee787org.meshtastic.core.ui.theme.DiscoveryMapColors
Tff7b72import T7ee787org.meshtastic.core.ui.util.DiscoveryMapNode
Tff7b72import T7ee787org.meshtastic.core.ui.util.DiscoveryNeighborType
Tff7b72import T7ee787org.osmdroid.util.BoundingBox
Tff7b72import T7ee787org.osmdroid.util.GeoPoint
Tff7b72import T7ee787org.osmdroid.views.overlay.Marker
Tff7b72import T7ee787org.osmdroid.views.overlay.Polyline

Tff7b72private Tff7b72const Tff7b72val Te6edf3SINGLE_POINT_ZOOM Tff7b72= T79c0ff1T79c0ff4.0
Tff7b72private Tff7b72const Tff7b72val Te6edf3ZOOM_OUT_LEVELS Tff7b72= T79c0ff0.5

T8b949e/**
* OSMDroid implementation of the discovery map. Renders discovered node markers color-coded by neighbor type (green =
* direct, blue = mesh) with polylines from the user position to direct neighbors. Auto-zooms to fit all markers.
*/
Tf0883e@Composable
Tff7b72fun Td2a8ffDiscoveryOsmMapTb4b4b4(
Te6edf3userLatitudeTb4b4b4: Tffa657DoubleTb4b4b4,
Te6edf3userLongitudeTb4b4b4: Tffa657DoubleTb4b4b4,
Te6edf3nodesTb4b4b4: Te6edf3ListTff7b72<Te6edf3DiscoveryMapNodeTff7b72>Tb4b4b4,
Te6edf3modifierTb4b4b4: Te6edf3Modifier Tff7b72= Te6edf3ModifierTb4b4b4,
Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3context Tff7b72= Te6edf3LocalContextTb4b4b4.Te6edf3current
Tff7b72val Te6edf3density Tff7b72= Te6edf3LocalDensityTb4b4b4.Te6edf3current
Tff7b72val Te6edf3hasValidUserPosition Tff7b72= Te6edf3userLatitude Tff7b72!Tff7b72= T79c0ff0.0 Tff7b72|Tff7b72| Te6edf3userLongitude Tff7b72!Tff7b72= T79c0ff0.0
Tff7b72val Te6edf3userGeoPoint Tff7b72= Te6edf3rememberTb4b4b4(Te6edf3userLatitudeTb4b4b4, Te6edf3userLongitudeTb4b4b4) Tb4b4b4{ Te6edf3GeoPointTb4b4b4(Te6edf3userLatitudeTb4b4b4, Te6edf3userLongitudeTb4b4b4) Tb4b4b4}
Tff7b72val Te6edf3validNodes Tff7b72= Te6edf3rememberTb4b4b4(Te6edf3nodesTb4b4b4) Tb4b4b4{ Te6edf3nodesTb4b4b4.Te6edf3filter Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3latitude Tff7b72!Tff7b72= T79c0ff0.0 Tff7b72|Tff7b72| Tffa657itTb4b4b4.Te6edf3longitude Tff7b72!Tff7b72= T79c0ff0.0 Tb4b4b4} Tb4b4b4}

T8b949e// Build bounding box from all points
Tff7b72val Te6edf3allGeoPoints Tff7b72=
Te6edf3rememberTb4b4b4(Te6edf3validNodesTb4b4b4, Te6edf3hasValidUserPositionTb4b4b4) Tb4b4b4{
Te6edf3buildList Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3hasValidUserPositionTb4b4b4) Te6edf3addTb4b4b4(Te6edf3userGeoPointTb4b4b4)
Te6edf3validNodesTb4b4b4.Te6edf3forEach Tb4b4b4{ Te6edf3addTb4b4b4(Te6edf3GeoPointTb4b4b4(Tffa657itTb4b4b4.Te6edf3latitudeTb4b4b4, Tffa657itTb4b4b4.Te6edf3longitudeTb4b4b4)Tb4b4b4) Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72val Te6edf3initialBounds Tff7b72=
Te6edf3rememberTb4b4b4(Te6edf3allGeoPointsTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3allGeoPointsTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Te6edf3BoundingBoxTb4b4b4(Tb4b4b4) Tff7b72else Te6edf3BoundingBoxTb4b4b4.Te6edf3fromGeoPointsTb4b4b4(Te6edf3allGeoPointsTb4b4b4)
Tb4b4b4}

Tff7b72var Te6edf3hasCentered Tff7b72by Te6edf3remember Tb4b4b4{ Te6edf3mutableStateOfTb4b4b4(Tff7b72falseTb4b4b4) Tb4b4b4}

Tff7b72val Te6edf3mapView Tff7b72= Te6edf3rememberMapViewWithLifecycleTb4b4b4(Te6edf3box Tff7b72= Te6edf3initialBoundsTb4b4b4, Te6edf3tileSource Tff7b72= Te6edf3CustomTileSourceTb4b4b4.Te6edf3getTileSourceTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4)

T8b949e// Camera auto-center once
Te6edf3LaunchedEffectTb4b4b4(Te6edf3allGeoPointsTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3hasCentered Tff7b72|Tff7b72| Te6edf3allGeoPointsTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72returnTf0883e@LaunchedEffect
Tff7b72if Tb4b4b4(Te6edf3allGeoPointsTb4b4b4.Te6edf3size Tff7b72=Tff7b72= T79c0ff1Tb4b4b4) Tb4b4b4{
Te6edf3mapViewTb4b4b4.Te6edf3controllerTb4b4b4.Te6edf3setCenterTb4b4b4(Te6edf3allGeoPointsTb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3mapViewTb4b4b4.Te6edf3controllerTb4b4b4.Te6edf3setZoomTb4b4b4(Te6edf3SINGLE_POINT_ZOOMTb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3mapViewTb4b4b4.Te6edf3zoomToBoundingBoxTb4b4b4(Te6edf3BoundingBoxTb4b4b4.Te6edf3fromGeoPointsTb4b4b4(Te6edf3allGeoPointsTb4b4b4)Tb4b4b4.Te6edf3zoomInTb4b4b4(Tff7b72-Te6edf3ZOOM_OUT_LEVELSTb4b4b4)Tb4b4b4, Tff7b72trueTb4b4b4)
Tb4b4b4}
Te6edf3hasCentered Tff7b72= Tff7b72true
Tb4b4b4}

Te6edf3AndroidViewTb4b4b4(
Te6edf3modifier Tff7b72= Te6edf3modifierTb4b4b4,
Te6edf3factory Tff7b72= Tb4b4b4{ Te6edf3mapViewTb4b4b4.Te6edf3apply Tb4b4b4{ Te6edf3setDestroyModeTb4b4b4(Tff7b72falseTb4b4b4) Tb4b4b4} Tb4b4b4}Tb4b4b4,
Te6edf3update Tff7b72= Tb4b4b4{ Te6edf3map Tff7b72-Tff7b72>
Te6edf3mapTb4b4b4.Te6edf3overlaysTb4b4b4.Te6edf3clearTb4b4b4(Tb4b4b4)
Te6edf3mapTb4b4b4.Te6edf3addCopyrightTb4b4b4(Tb4b4b4)
Te6edf3mapTb4b4b4.Te6edf3addScaleBarOverlayTb4b4b4(Te6edf3densityTb4b4b4)

T8b949e// User position marker
Tff7b72if Tb4b4b4(Te6edf3hasValidUserPositionTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3userMarker Tff7b72=
Te6edf3MarkerTb4b4b4(Te6edf3mapTb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3position Tff7b72= Te6edf3userGeoPoint
Te6edf3setAnchorTb4b4b4(Te6edf3MarkerTb4b4b4.Te6edf3ANCHOR_CENTERTb4b4b4, Te6edf3MarkerTb4b4b4.Te6edf3ANCHOR_BOTTOMTb4b4b4)
Te6edf3title Tff7b72= Ta5d6ff"Ta5d6ffYour PositionTa5d6ff"
Te6edf3icon Tff7b72= Te6edf3contextTb4b4b4.Te6edf3getDrawableTb4b4b4(Te6edf3androidTb4b4b4.Te6edf3RTb4b4b4.Te6edf3drawableTb4b4b4.Te6edf3ic_menu_mylocationTb4b4b4)
Tb4b4b4}
Te6edf3mapTb4b4b4.Te6edf3overlaysTb4b4b4.Te6edf3addTb4b4b4(Te6edf3userMarkerTb4b4b4)
Tb4b4b4}

T8b949e// Node markers
Te6edf3validNodesTb4b4b4.Te6edf3forEach Tb4b4b4{ Te6edf3node Tff7b72-Tff7b72>
Tff7b72val Te6edf3nodeGeoPoint Tff7b72= Te6edf3GeoPointTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3latitudeTb4b4b4, Te6edf3nodeTb4b4b4.Te6edf3longitudeTb4b4b4)
Tff7b72val Te6edf3marker Tff7b72=
Te6edf3MarkerTb4b4b4(Te6edf3mapTb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3position Tff7b72= Te6edf3nodeGeoPoint
Te6edf3setAnchorTb4b4b4(Te6edf3MarkerTb4b4b4.Te6edf3ANCHOR_CENTERTb4b4b4, Te6edf3MarkerTb4b4b4.Te6edf3ANCHOR_BOTTOMTb4b4b4)
Te6edf3title Tff7b72= Te6edf3nodeTb4b4b4.Te6edf3longName Tff7b72?: Te6edf3nodeTb4b4b4.Te6edf3shortName Tff7b72?: Ta5d6ff"Ta5d6ffUnknownTa5d6ff"
Te6edf3snippet Tff7b72= Ta5d6ff"Ta5d6ffSNR: Tffd700${Te6edf3MetricFormatterTb4b4b4.Te6edf3snrTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3snrTb4b4b4)Tffd700}Ta5d6ff / RSSI: Tffd700${Te6edf3MetricFormatterTb4b4b4.Te6edf3rssiTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3rssiTb4b4b4)Tffd700}Ta5d6ff"

Tff7b72val Te6edf3drawableId Tff7b72=
Tff7b72if Tb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3isSensorNodeTb4b4b4) Tb4b4b4{
Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3appTb4b4b4.Te6edf3RTb4b4b4.Te6edf3drawableTb4b4b4.Te6edf3ic_thermostat
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3appTb4b4b4.Te6edf3RTb4b4b4.Te6edf3drawableTb4b4b4.Te6edf3ic_person
Tb4b4b4}
Te6edf3icon Tff7b72= Te6edf3contextTb4b4b4.Te6edf3getDrawableTb4b4b4(Te6edf3drawableIdTb4b4b4)

T8b949e// Default OSM marker handles color tinting via icon overlay or custom drawables if needed,
T8b949e// but setting the icon directly overrides the default teardrop pin.
Tb4b4b4}
Te6edf3mapTb4b4b4.Te6edf3overlaysTb4b4b4.Te6edf3addTb4b4b4(Te6edf3markerTb4b4b4)
Tb4b4b4}

T8b949e// Polylines from user to direct neighbors
Tff7b72if Tb4b4b4(Te6edf3hasValidUserPositionTb4b4b4) Tb4b4b4{
Te6edf3validNodes
Tb4b4b4.Te6edf3filter Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3neighborType Tff7b72=Tff7b72= Te6edf3DiscoveryNeighborTypeTb4b4b4.Te6edf3DIRECT Tb4b4b4}
Tb4b4b4.Te6edf3forEach Tb4b4b4{ Te6edf3node Tff7b72-Tff7b72>
Tff7b72val Te6edf3polyline Tff7b72=
Te6edf3PolylineTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3setPointsTb4b4b4(Te6edf3listOfTb4b4b4(Te6edf3userGeoPointTb4b4b4, Te6edf3GeoPointTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3latitudeTb4b4b4, Te6edf3nodeTb4b4b4.Te6edf3longitudeTb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3outlinePaintTb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3color Tff7b72= Te6edf3DiscoveryMapColorsTb4b4b4.Te6edf3DirectLineTb4b4b4.Te6edf3toArgbTb4b4b4(Tb4b4b4)
Te6edf3strokeWidth Tff7b72= Te6edf3withTb4b4b4(Te6edf3densityTb4b4b4) Tb4b4b4{ T79c0ff3.Te6edf3dpTb4b4b4.Te6edf3toPxTb4b4b4(Tb4b4b4) Tb4b4b4}
Te6edf3strokeCap Tff7b72= Te6edf3PaintTb4b4b4.Te6edf3CapTb4b4b4.Te6edf3ROUND
Te6edf3style Tff7b72= Te6edf3PaintTb4b4b4.Te6edf3StyleTb4b4b4.Te6edf3STROKE
Tb4b4b4}
Tb4b4b4}
Te6edf3mapTb4b4b4.Te6edf3overlaysTb4b4b4.Te6edf3addTb4b4b4(Te6edf3polylineTb4b4b4)
Tb4b4b4}
Tb4b4b4}

Te6edf3mapTb4b4b4.Te6edf3invalidateTb4b4b4(Tb4b4b4)
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tb4b4b4}

Served by rngit 1.5.0 - Generated in 0.06s